package com.bsg.upm.service;

import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bsg.upm.check.CheckResult;
import com.bsg.upm.check.HostCheck;
import com.bsg.upm.constant.DictConstants;
import com.bsg.upm.constant.DictTypeConstants;
import com.bsg.upm.constant.OperateDictConstants;
import com.bsg.upm.constant.OperateDictTypeConstants;
import com.bsg.upm.constant.SubTaskDictConstants;
import com.bsg.upm.constant.SysConstants;
import com.bsg.upm.constant.TaskDictConstants;
import com.bsg.upm.constant.TaskDictTypeConstants;
import com.bsg.upm.dto.HostDto;
import com.bsg.upm.entity.AreaEntity;
import com.bsg.upm.entity.ClusterEntity;
import com.bsg.upm.entity.DefinitionSubTaskConfigEntity;
import com.bsg.upm.entity.HostEntity;
import com.bsg.upm.entity.OperateLogEntity;
import com.bsg.upm.entity.SanEntity;
import com.bsg.upm.entity.SiteEntity;
import com.bsg.upm.entity.SubTaskEntity;
import com.bsg.upm.entity.TaskEntity;
import com.bsg.upm.entity.UnitEntity;
import com.bsg.upm.entity.UserEntity;
import com.bsg.upm.excel.ExcelUtil;
import com.bsg.upm.exception.APIException;
import com.bsg.upm.http.HttpClientUtils;
import com.bsg.upm.http.RespJson;
import com.bsg.upm.http.RespJsonFactory;
import com.bsg.upm.util.DateUtils;
import com.bsg.upm.util.PrimaryKeyUtils;

/**
 * 主机管理业务处理类
 * 
 * @author HCK
 *
 */
@Service
public class HostService extends BaseService {

	@Resource
	private HostCheck hostCheck;

	/**
	 * 主机查询
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	public RespJson list(Map<String, Object> paramMap) throws APIException {
		try {
			// 结果集
			JSONArray results = new JSONArray();

			// 获取指定条件的主机
			List<HostEntity> hosts = hostDao.list(paramMap);
			if (hosts.size() > 0) {
				String siteId = (String) paramMap.get("siteId");

				// 从MGM获取主机信息
				JSONArray mgmHostInfos = listHostInfoFromMGM(siteId);

				for (HostEntity host : hosts) {
					// 获取指定的主机信息(来源MGM)
					JSONObject mgmHostInfo = findHostInfoFromMgm(mgmHostInfos, host.getRelateId());

					// 构建主机展示对象
					HostDto hostDto = buildShowDto(host, false, mgmHostInfo);
					results.add(hostDto);
				}
			}
			return RespJsonFactory.buildOK(results);
		} catch (Exception e) {
			logger.error("主机查询异常", e);
			throw new APIException("主机查询异常:" + e.getMessage());
		}
	}

	/**
	 * 主机详情
	 * 
	 * @param hostId
	 *            主机编码
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	public RespJson get(String hostId) throws APIException {
		try {
			// 获取指定的主机
			HostEntity host = hostDao.get(hostId);
			if (hostDao == null) {
				return RespJsonFactory.build(HttpStatus.SC_GONE, "该主机不存在");
			}

			JSONObject mgmHostInfo = null;
			if (StringUtils.isNotBlank(host.getRelateId())) {
				// 站点
				String siteId = host.getCluster().getArea().getSite().getId();
				// 从MGM获取指定的主机信息
				mgmHostInfo = getHostInfoFromMGM(siteId, host.getRelateId());
			}

			// 构建主机展示对象
			HostDto hostDto = buildShowDto(host, true, mgmHostInfo);

			return RespJsonFactory.buildOK(hostDto);
		} catch (Exception e) {
			logger.error("主机获取异常", e);
			throw new APIException("主机获取异常:" + e.getMessage());
		}
	}

	/**
	 * 主机注册
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson save(Map<String, Object> paramMap) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_REGISTER;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// 主机注册检查
			CheckResult chkRS = hostCheck.checkSave(paramMap);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			// 构建主机对象
			HostEntity host = buildHost(paramMap);
			hostDao.save(host);

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_HOST, operateAcion, host.getId(), host.getName(),
					host.getCreateDateTime());

			return RespJsonFactory.buildCreated();
		} catch (Exception e) {
			logger.error("主机" + operateAcionText + "异常", e);
			throw new APIException("主机" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 主机编辑
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson update(Map<String, Object> paramMap) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_UPDATE;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// 主机编辑检查
			CheckResult chkRS = hostCheck.checkUpdate(paramMap);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			// 构建主机对象
			HostEntity host = buildHostToUpdate(paramMap);
			hostDao.update(host);

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_HOST, operateAcion, host.getId(), host.getName());

			return RespJsonFactory.buildOK();
		} catch (Exception e) {
			logger.error("主机" + operateAcionText + "异常", e);
			throw new APIException("主机" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 主机容器上限编辑
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson updateMgmHost(Map<String, Object> paramMap) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_UPDATE_MGM_HOST;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {

			// 主机编辑检查
			CheckResult chkRS = hostCheck.checkUpdateMaxContainer(paramMap);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			String hostId = (String) paramMap.get("hostId");
			// 获取指定的主机
			HostEntity host = hostDao.get(hostId);

			String siteId = host.getCluster().getArea().getSite().getId();
			updateHostFromMGM(siteId, host.getRelateId(), paramMap);

			Integer maxContainer = (Integer) paramMap.get("maxContainer");
			host.setMaxContainer(maxContainer);
			hostDao.update(host);

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_HOST, operateAcion, host.getId(), host.getName());

			return RespJsonFactory.buildOK();
		} catch (Exception e) {
			logger.error("主机" + operateAcionText + "异常", e);
			throw new APIException("主机" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 主机入库
	 * 
	 * @param hostId
	 *            主机编码
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	public RespJson input(String hostId) throws APIException {
		// 事务定义
		DefaultTransactionDefinition def = null;
		// 事务状态
		TransactionStatus txStatus = null;

		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_INPUT;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// 获取指定的主机
			HostEntity host = hostDao.get(hostId);

			// 主机入库检查
			CheckResult chkRS = hostCheck.checkInput(host);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			def = new DefaultTransactionDefinition();
			def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
			txStatus = txManager.getTransaction(def);

			// 保存操作日志
			OperateLogEntity operateLog = saveOperateLog(OperateDictConstants.MODEL_HOST, operateAcion, host.getId(),
					host.getName());

			// 构建入库任务
			TaskEntity task = buildInputHostTask(host, operateLog);
			saveTask(task);
			txManager.commit(txStatus);

			// 开启任务
			startTask(task);
			return RespJsonFactory.buildOK();
		} catch (Exception e) {
			if (txStatus != null) {
				txManager.rollback(txStatus);
			}
			logger.error("主机" + operateAcionText + "异常", e);
			throw new APIException("主机" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 主机出库
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	public RespJson output(Map<String, Object> paramMap) throws APIException {
		// 事务定义
		DefaultTransactionDefinition def = null;
		// 事务状态
		TransactionStatus txStatus = null;

		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_OUTPUT;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			String hostId = (String) paramMap.get("id");

			// 获取指定的主机
			HostEntity host = hostDao.get(hostId);

			// 主机出库检查
			CheckResult chkRS = hostCheck.checkOutput(host);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			def = new DefaultTransactionDefinition();
			def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
			txStatus = txManager.getTransaction(def);

			// 保存操作日志
			OperateLogEntity operateLog = saveOperateLog(OperateDictConstants.MODEL_HOST, operateAcion, host.getId(),
					host.getName());

			// 构建出库任务
			TaskEntity task = buildOutputHostTask(host, operateLog, paramMap);
			saveTask(task);
			txManager.commit(txStatus);

			// 开启任务
			startTask(task);
			return RespJsonFactory.buildOK();
		} catch (Exception e) {
			if (txStatus != null) {
				txManager.rollback(txStatus);
			}
			logger.error("主机" + operateAcionText + "异常", e);
			throw new APIException("主机" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 主机启用/停用
	 * 
	 * @param id
	 *            主机编码
	 * @param enable
	 *            是否启用
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson enable(String id, boolean enable) throws APIException {
		// 事务定义
		DefaultTransactionDefinition def = null;
		// 事务状态
		TransactionStatus txStatus = null;

		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_DISABLE;
		if (enable) {
			operateAcion = OperateDictConstants.ACTION_ENABLE;
		}
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// 获取指定的主机
			HostEntity host = hostDao.get(id);

			// 主机启停检查
			CheckResult chkRS = null;
			if (enable) {
				chkRS = hostCheck.checkEnable(host);
			} else {
				chkRS = hostCheck.checkDisable(host);
			}
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			def = new DefaultTransactionDefinition();
			def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
			txStatus = txManager.getTransaction(def);

			// 保存操作日志
			OperateLogEntity operateLog = saveOperateLog(OperateDictConstants.MODEL_HOST, operateAcion, host.getId(),
					host.getName());

			// 构建启停任务
			TaskEntity task = null;
			if (enable) {
				task = buildEnableHostTask(host, operateLog);
			} else {
				task = buildDisableHostTask(host, operateLog);
			}
			saveTask(task);
			txManager.commit(txStatus);

			// 开启任务
			startTask(task);
			return RespJsonFactory.buildOK();
		} catch (Exception e) {
			if (txStatus != null) {
				txManager.rollback(txStatus);
			}
			logger.error("主机" + operateAcionText + "异常", e);
			throw new APIException("主机" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 主机注销
	 * 
	 * @param id
	 *            主机编码
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson remove(String id) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_DEREGISTER;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// 获取指定的主机
			HostEntity host = hostDao.get(id);

			// 主机注销检查
			CheckResult chkRS = hostCheck.checkRemove(host);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			hostDao.remove(id);

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_HOST, operateAcion, id, host.getName());

			return RespJsonFactory.buildNoContent();
		} catch (Exception e) {
			logger.error("主机" + operateAcionText + "异常", e);
			throw new APIException("主机" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 主机批量注册
	 * 
	 * @param siteId
	 *            站点编码
	 * @param file
	 *            上传文件
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	@SuppressWarnings("unchecked")
	@Transactional(rollbackFor = APIException.class)
	public RespJson upload(String siteId, MultipartFile file) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_REGISTER;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			Map<String, Object> paramMap = new HashMap<>();
			paramMap.put("siteId", siteId);

			// 获取指定条件的主机
			List<HostEntity> hosts = hostDao.list(paramMap);

			// 获取指定条件的集群
			List<ClusterEntity> clusters = clusterDao.list(paramMap);

			// 获取指定条件的SAN
			List<SanEntity> sans = sanDao.list(paramMap);

			// 读取Excel
			Map<String, Object> excelData = ExcelUtil.read(file.getInputStream(), file.getOriginalFilename());

			// 批量注册检查
			try {
				CheckResult chkRS = hostCheck.checkUpload(excelData, hosts, clusters, sans);
				if (chkRS.isError()) {
					return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
				}
			} catch (Exception e) {
				logger.error("主机" + operateAcionText + "异常", e);
				throw new APIException("Excel格式错误");
			}

			Date date = systemDao.getCurrentDateTime();
			for (Map.Entry<String, Object> entry : excelData.entrySet()) {
				List<Object> rows = (List<Object>) entry.getValue();
				for (int i = 1; i < rows.size(); i++) {
					List<Object> cells = (List<Object>) rows.get(i);
					HostEntity host = new HostEntity();
					for (ClusterEntity cluster : clusters) {
						if (cluster.getName().equals(cells.get(1))
								&& cluster.getArea().getName().equals(cells.get(0))) {
							host.setCluster(cluster);
							break;
						}
					}
					host.setId(PrimaryKeyUtils.uniqueId());
					host.setName((String) cells.get(2));
					host.setSshIp((String) cells.get(3));
					host.setSshUser((String) cells.get(4));
					host.setSshPassword((String) cells.get(5));
					host.setMaxContainer(Integer.parseInt((String) cells.get(6)));
					host.setRoom((String) cells.get(7));
					host.setSeat((String) cells.get(8));
					if (cells.get(9) != null) {
						host.setHddDev((String) cells.get(9));
					}
					if (cells.get(10) != null) {
						host.setHddDev((String) cells.get(10));
					}
					if (cells.get(11) != null) {
						for (SanEntity san : sans) {
							if (san.getName().equals(cells.get(11))) {
								host.setSan(san);
								break;
							}
						}
					}
					host.setStatus(DictConstants.HOST_STATUS_INPUT_NO);
					host.setCreateDateTime(date);
					UserEntity user = getUser();
					String username = user.getUsername();
					host.setCreateUserLoginName(username);
					hostDao.save(host);
				}
				break;
			}

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_HOST, operateAcion, "批量注册", "批量注册");

			return RespJsonFactory.buildCreated();
		} catch (Exception e) {
			logger.error("主机" + operateAcionText + "异常", e);
			throw new APIException("主机" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 主机下载
	 * 
	 * @param filePath
	 *            模板路径
	 * @param siteId
	 *            站点编码
	 * @return Workbook
	 * @throws APIException
	 *             API异常处理类
	 */
	public Workbook download(String filePath, String siteId) throws APIException {
		try {
			Workbook workbook = ExcelUtil.getWorkbook(new File(filePath));
			Sheet sheet = workbook.getSheetAt(0);
			int titleCnt = 1;
			Row baseRow = sheet.getRow(titleCnt);

			Map<String, Object> paramMap = new HashMap<>();
			paramMap.put("siteId", siteId);
			List<HostEntity> hosts = hostDao.list(paramMap);
			if (hosts.size() > 0) {
				// 从MGM获取主机信息
				JSONArray mgmHostInfos = listHostInfoFromMGM(siteId);

				for (int i = 0; i < hosts.size(); i++) {
					HostEntity host = hosts.get(i);
					// 获取指定的主机信息(来源MGM)
					JSONObject mgmHostInfo = findHostInfoFromMgm(mgmHostInfos, host.getRelateId());

					Row row = sheet.getRow(titleCnt + i);
					if (row == null) {
						row = sheet.createRow(titleCnt + i);
						ExcelUtil.copyRow(workbook, baseRow, row);
					}
					row.getCell(0).setCellValue(host.getName());
					row.getCell(1).setCellValue(host.getCluster().getArea().getName());
					row.getCell(2).setCellValue(host.getCluster().getName());
					row.getCell(3).setCellValue(host.getSshIp());
					row.getCell(4).setCellValue(host.getMaxContainer());
					row.getCell(5).setCellValue(host.getRoom());
					row.getCell(6).setCellValue(host.getSeat());
					row.getCell(7).setCellValue(DateUtils.dateTimeToString(host.getCreateDateTime()));
					row.getCell(8).setCellValue(
							dictTypeCache.getTextFromCache(DictTypeConstants.HOST_STATUS, host.getStatus()));
					row.getCell(9).setCellValue(host.getDescription());
					row.getCell(10).setCellValue(mgmHostInfo.getString("register_at"));
					row.getCell(11).setCellValue(mgmHostInfo.getString("id"));
					JSONObject engine = mgmHostInfo.getJSONObject("Engine");
					if (engine != null) {
						row.getCell(12).setCellValue(engine.getString("id"));
						row.getCell(13).setCellValue(engine.getString("is_healthy"));
						row.getCell(14).setCellValue(engine.getIntValue("cpus"));
						row.getCell(15).setCellValue(engine.getIntValue("cpus") - engine.getIntValue("free_cpus"));
						row.getCell(16).setCellValue(engine.getLongValue("memory") / 1024 / 1024 / 1024);
						row.getCell(17)
								.setCellValue((engine.getLongValue("memory") - engine.getLongValue("free_memory"))
										/ 1024 / 1024 / 1024);
					}
					JSONArray volumeDriverJsonArr = mgmHostInfo.getJSONArray("volume_drivers");
					if (volumeDriverJsonArr != null) {
						for (int j = 0; j < volumeDriverJsonArr.size(); j++) {
							JSONObject volumeDriverInfo = volumeDriverJsonArr.getJSONObject(j);
							if (volumeDriverInfo.getString("type").equals("local:HDD")) {
								row.getCell(18)
										.setCellValue(volumeDriverInfo.getLongValue("total") / 1024 / 1024 / 1024);
								row.getCell(19).setCellValue(
										(volumeDriverInfo.getLongValue("total") - volumeDriverInfo.getLongValue("free"))
												/ 1024 / 1024 / 1024);
								break;
							} else if (volumeDriverInfo.getString("type").equals("local:SSD")) {
								row.getCell(20)
										.setCellValue(volumeDriverInfo.getLongValue("total") / 1024 / 1024 / 1024);
								row.getCell(21).setCellValue(
										(volumeDriverInfo.getLongValue("total") - volumeDriverInfo.getLongValue("free"))
												/ 1024 / 1024 / 1024);
							}
						}
					}
				}
			}

			// 列宽自适应
			ExcelUtil.autoSizeColumn(sheet);

			return workbook;
		} catch (Exception e) {
			logger.error("主机下载异常", e);
			throw new APIException("主机下载异常" + e.getMessage());
		}
	}

	/**
	 * 从MGM获取主机信息
	 * 
	 * @param siteId
	 *            站点编码
	 * @return JSONArray MGM主机集合
	 * @throws APIException
	 *             API异常处理类
	 */
	private JSONArray listHostInfoFromMGM(String siteId) throws APIException {
		String urlPattern = "/{0}/hosts";
		String url = MessageFormat.format(urlPattern, SysConstants.MGM_VERSION);
		RespJson httpRespJson = sendHttpGet(siteId, SysConstants.INTERFACE_TYPE_MGM, url);
		if (httpRespJson.getStatus() == HttpStatus.SC_OK) {
			return ((JSONArray) httpRespJson.getData());
		} else {
			throw new APIException(httpRespJson.getMsg());
		}
	}

	/**
	 * 从MGM主机列表中获取指定的主机信息
	 * 
	 * @param mgmHostInfos
	 *            MGM主机集合
	 * @param mgmHostId
	 *            MGM主机编码
	 * @return MGM主机信息
	 */
	private JSONObject findHostInfoFromMgm(JSONArray mgmHostInfos, String mgmHostId) {
		if (mgmHostInfos == null) {
			return null;
		}
		for (int i = 0; i < mgmHostInfos.size(); i++) {
			JSONObject mgmHostInfo = mgmHostInfos.getJSONObject(i);
			if (mgmHostInfo.getString("id").equals(mgmHostId)) {
				return mgmHostInfo;
			}
		}
		return null;
	}

	/**
	 * 从MGM获取指定的主机信息
	 * 
	 * @param siteId
	 *            站点编码
	 * @param mgmHostId
	 *            MGM主机编码
	 * @return MGM主机信息
	 * @throws APIException
	 *             API异常处理类
	 */
	public JSONObject getHostInfoFromMGM(String siteId, String mgmHostId) throws APIException {
		String urlPattern = "/{0}/hosts/{1}";
		String url = MessageFormat.format(urlPattern, SysConstants.MGM_VERSION, mgmHostId);
		RespJson httpRespJson = sendHttpGet(siteId, SysConstants.INTERFACE_TYPE_MGM, url);
		if (httpRespJson.getStatus() == HttpStatus.SC_OK) {
			return ((JSONObject) httpRespJson.getData());
		} else {
			throw new APIException(httpRespJson.getMsg());
		}
	}

	/**
	 * 构建主机展示对象
	 * 
	 * @param host
	 *            主机对象
	 * @param showDetail
	 *            是否展示详情
	 * @param mgmHostInfo
	 *            MGM主机对象
	 * @return 主机展示对象
	 */
	private HostDto buildShowDto(HostEntity host, boolean showDetail, JSONObject mgmHostInfo) {
		HostDto hostDto = new HostDto();
		ClusterEntity cluster = host.getCluster();
		AreaEntity area = cluster.getArea();
		SiteEntity site = area.getSite();
		hostDto.setSiteId(site.getId());
		hostDto.setSiteName(site.getName());
		hostDto.setClusterId(cluster.getId());
		hostDto.setClusterName(cluster.getName());
		hostDto.setAreaId(area.getId());
		hostDto.setAreaName(area.getName());
		hostDto.setId(host.getId());
		hostDto.setName(host.getName());
		hostDto.setSshIp(host.getSshIp());
		hostDto.setSshUser(host.getSshUser());
		hostDto.setSshPassword("******");
		hostDto.setMaxContainer(host.getMaxContainer());
		hostDto.setRoom(host.getRoom());
		hostDto.setSeat(host.getSeat());
		hostDto.setHddDev(host.getHddDev());
		hostDto.setSsdDev(host.getSsdDev());
		hostDto.setStatus(host.getStatus());
		hostDto.setStatusText(dictTypeCache.getTextFromCache(DictTypeConstants.HOST_STATUS, hostDto.getStatus()));
		hostDto.setDescription(host.getDescription());
		List<TaskEntity> tasks = host.getTasks();
		if (tasks != null && tasks.size() > 0) {
			hostDto.setTaskStatus(tasks.get(0).getStatus());
			hostDto.setTaskStatusText(
					dictTypeCache.getTextFromCache(TaskDictTypeConstants.TASK_STATUS, hostDto.getTaskStatus()));
		}
		hostDto.setRelateId(host.getRelateId());
		hostDto.setCreateDateTime(DateUtils.dateTimeToString(host.getCreateDateTime()));
		hostDto.setCreateLoginUserName(host.getCreateUserLoginName());
		List<Map<String, Object>> unitMaps = new ArrayList<>();
		hostDto.setUnits(unitMaps);
		if (mgmHostInfo != null) {
			int unitCnt = 0;
			JSONArray containerJsonArr = mgmHostInfo.getJSONArray("containers");
			if (containerJsonArr != null) {
				unitCnt = containerJsonArr.size();
				if (unitCnt > 0) {
					List<UnitEntity> units = unitDao.listBySiteId(site.getId());
					for (int i = 0; i < unitCnt; i++) {
						JSONObject containerInfo = containerJsonArr.getJSONObject(i);
						JSONObject labelsInfo = containerInfo.getJSONObject("labels");
						for (UnitEntity unit : units) {
							if (StringUtils.isNotBlank(unit.getRelateId())) {
								if (unit.getRelateId().equals(labelsInfo.getString("mgm.unit.id"))) {
									Map<String, Object> unitMap = new HashMap<>();
									unitMaps.add(unitMap);

									unitMap.put("servName", unit.getSubServ().getServ().getServName());
									unitMap.put("owner", unit.getSubServ().getServ().getOrder().getOwner());
									unitMap.put("unitType",
											unit.getSubServ().getSubOrder().getDefinitionSubServ().getName());
									unitMap.put("unitName", unit.getRelateName());
									break;
								}
							}
						}
					}
				}
			}
			hostDto.setUnitCnt(unitCnt);

			hostDto.setInputDateTime(mgmHostInfo.getString("register_at"));

			JSONObject engineInfo = mgmHostInfo.getJSONObject("Engine");
			if (engineInfo != null) {
				hostDto.setCpuCnt(engineInfo.getIntValue("cpus"));
				hostDto.setUsedCpuCnt(engineInfo.getIntValue("cpus") - engineInfo.getIntValue("free_cpus"));

				hostDto.setMemCnt(engineInfo.getLongValue("memory"));
				hostDto.setUsedMemCnt(engineInfo.getLongValue("free_memory"));

				hostDto.setKernelVersion(engineInfo.getString("kernel_version"));
				hostDto.setOs(engineInfo.getString("os"));
				hostDto.setOsType(engineInfo.getString("os_type"));
				hostDto.setArchitecture(engineInfo.getString("architecture"));
			}

			JSONArray volumeDriverJsonArr = mgmHostInfo.getJSONArray("volume_drivers");
			if (volumeDriverJsonArr != null) {
				for (int i = 0; i < volumeDriverJsonArr.size(); i++) {
					JSONObject volumeDriverInfo = volumeDriverJsonArr.getJSONObject(i);
					if (volumeDriverInfo.getString("type").equals("local:HDD")) {
						hostDto.setHddCnt(volumeDriverInfo.getLongValue("total"));
						hostDto.setUsedHddCnt(
								volumeDriverInfo.getLongValue("total") - volumeDriverInfo.getLongValue("free"));
						break;
					} else if (volumeDriverInfo.getString("type").equals("local:SSD")) {
						hostDto.setSsdCnt(volumeDriverInfo.getLongValue("total"));
						hostDto.setUsedSsdCnt(
								volumeDriverInfo.getLongValue("total") - volumeDriverInfo.getLongValue("free"));
					}
				}
			}
		}
		return hostDto;
	}

	/**
	 * 构建主机对象
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return 主机对象
	 */
	private HostEntity buildHost(Map<String, Object> paramMap) {
		HostEntity host = new HostEntity();
		host.setId(PrimaryKeyUtils.uniqueId());
		ClusterEntity cluster = new ClusterEntity();
		cluster.setId((String) paramMap.get("cluster"));
		host.setCluster(cluster);
		host.setName(StringUtils.trim((String) paramMap.get("name")));
		host.setSshIp(StringUtils.trim((String) paramMap.get("sshIp")));
		host.setSshUser(StringUtils.trim((String) paramMap.get("sshUser")));
		host.setSshPassword(StringUtils.trim((String) paramMap.get("sshPassword")));
		host.setRoom(StringUtils.trim((String) paramMap.get("room")));
		host.setSeat(StringUtils.trim((String) paramMap.get("seat")));
		host.setHddDev(StringUtils.trim((String) paramMap.get("hddDev")));
		host.setSsdDev(StringUtils.trim((String) paramMap.get("ssdDev")));
		if (StringUtils.isNotBlank((String) paramMap.get("san"))) {
			SanEntity san = new SanEntity();
			san.setId((String) paramMap.get("san"));
			host.setSan(san);
		}
		host.setMaxContainer((Integer) paramMap.get("maxContainer"));
		host.setStatus(DictConstants.HOST_STATUS_INPUT_NO);
		if (paramMap.containsKey("description")) {
			host.setDescription(StringUtils.trim((String) paramMap.get("description")));
		}
		host.setCreateDateTime(systemDao.getCurrentDateTime());
		UserEntity user = getUser();
		String username = user.getUsername();
		host.setCreateUserLoginName(username);
		return host;
	}

	/**
	 * 构建主机对象用于更新操作
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return 主机对象
	 */
	private HostEntity buildHostToUpdate(Map<String, Object> paramMap) {
		HostEntity host = hostDao.get((String) paramMap.get("hostId"));

		if (paramMap.containsKey("cluster")) {
			String clusterId = (String) paramMap.get("cluster");
			if (StringUtils.isNotBlank(clusterId)) {
				ClusterEntity cluster = new ClusterEntity();
				cluster.setId(clusterId);
				host.setCluster(cluster);
			}
		}

		if (paramMap.containsKey("name")) {
			host.setName(StringUtils.trim((String) paramMap.get("name")));
		}

		if (paramMap.containsKey("sshIp")) {
			host.setSshIp(StringUtils.trim((String) paramMap.get("sshIp")));
		}

		if (paramMap.containsKey("sshUser")) {
			host.setSshUser(StringUtils.trim((String) paramMap.get("sshUser")));
		}

		if (paramMap.containsKey("sshPassword")) {
			host.setSshPassword(StringUtils.trim((String) paramMap.get("sshPassword")));
		}

		if (paramMap.containsKey("room")) {
			host.setRoom(StringUtils.trim((String) paramMap.get("room")));
		}

		if (paramMap.containsKey("seat")) {
			host.setSeat(StringUtils.trim((String) paramMap.get("seat")));
		}

		if (paramMap.containsKey("hddDev")) {
			host.setHddDev(StringUtils.trim((String) paramMap.get("hddDev")));
		}

		if (paramMap.containsKey("ssdDev")) {
			host.setSsdDev(StringUtils.trim((String) paramMap.get("ssdDev")));
		}

		if (paramMap.containsKey("san")) {
			SanEntity san = new SanEntity();
			san.setId((String) paramMap.get("san"));
			host.setSan(san);
			host.setSsdDev(StringUtils.trim((String) paramMap.get("ssdDev")));
		}

		if (paramMap.containsKey("maxContainer")) {
			host.setMaxContainer((Integer) paramMap.get("maxContainer"));
		}

		if (paramMap.containsKey("description")) {
			host.setDescription(StringUtils.trim((String) paramMap.get("description")));
		}

		return host;
	}

	/**
	 * 构建主机入库任务
	 * 
	 * @param host
	 *            主机对象
	 * @param operateLog
	 *            操作日志对象
	 * @return 任务对象
	 */
	private TaskEntity buildInputHostTask(HostEntity host, OperateLogEntity operateLog) {
		TaskEntity task = new TaskEntity();
		task.setId(PrimaryKeyUtils.uniqueId());
		task.setSite(host.getCluster().getArea().getSite());
		task.setObjType(TaskDictConstants.OBJ_TYPE_HOST);
		task.setObjId(host.getId());
		task.setObjName(host.getName());
		task.setObj(host);
		task.setActionType(TaskDictConstants.ACTION_TYPE_INPUT);
		task.setOperateLog(operateLog);
		UserEntity user = getUser();
		String username = user.getUsername();
		task.setOwner(username);
		task.setCreateUserLoginName(username);
		task.setStatus(TaskDictConstants.STATUS_INPUT_RUNNING);
		task.setStartDateTime(operateLog.getCreateDateTime());

		List<SubTaskEntity> subTasks = buildInputHostSubTasks(host, task.getStartDateTime());
		task.setSubTasks(subTasks);
		return task;
	}

	/**
	 * 构建主机入库子任务
	 * 
	 * @param host
	 *            主机对象
	 * @param date
	 *            任务开始时间
	 * @return 子任务集合
	 */
	private List<SubTaskEntity> buildInputHostSubTasks(HostEntity host, Date date) {
		List<SubTaskEntity> subTasks = new ArrayList<SubTaskEntity>();

		int priority = 1;
		if (StringUtils.isNotBlank(host.getRelateId())) {
			SubTaskEntity subTask_output = new SubTaskEntity();
			subTasks.add(subTask_output);
			subTask_output.setId(PrimaryKeyUtils.uniqueId());
			subTask_output.setObjType(SubTaskDictConstants.OBJ_TYPE_HOST);
			subTask_output.setObjId(host.getId());
			subTask_output.setObjName(host.getName());
			subTask_output.setObj(host);
			subTask_output.setActionType(SubTaskDictConstants.ACTION_TYPE_OUTPUT);
			subTask_output.setAsync(false);
			subTask_output.setTimeout(HttpClientUtils.requestConfig.getSocketTimeout() + 10000);
			subTask_output.setStatus(SubTaskDictConstants.STATUS_RUNNING);
			subTask_output.setStartDateTime(date);
			String url = null;
			String relateId = host.getRelateId();
			if (relateId != null) {
				String sshUser = host.getSshUser();
				String sshPassword = host.getSshPassword();
				url = "/" + SysConstants.MGM_VERSION + "/hosts/" + relateId + "?username=" + sshUser + "&password="
						+ sshPassword;
			}
			subTask_output.setUrl(url);
			subTask_output.setMethodType(HttpClientUtils.METHOD_DELETE);
			subTask_output.setParam(null);
			subTask_output.setPriority(priority);
			priority++;
		}

		SubTaskEntity subTask_input = new SubTaskEntity();
		subTasks.add(subTask_input);

		subTask_input.setId(PrimaryKeyUtils.uniqueId());
		subTask_input.setObjType(SubTaskDictConstants.OBJ_TYPE_HOST);
		subTask_input.setObjId(host.getId());
		subTask_input.setObjName(host.getName());
		subTask_input.setObj(host);
		subTask_input.setActionType(SubTaskDictConstants.ACTION_TYPE_INPUT);
		subTask_input.setAsync(true);
		DefinitionSubTaskConfigEntity dfSubTaskConfig = definitionSubTaskConfigCache
				.getDfSubTaskConfigFromCache(subTask_input.getObjType(), subTask_input.getActionType());
		subTask_input.setTimeout(dfSubTaskConfig.getTimeout());
		if (priority == 1) {
			subTask_input.setStatus(SubTaskDictConstants.STATUS_RUNNING);
			subTask_input.setStartDateTime(date);
		} else {
			subTask_input.setStatus(SubTaskDictConstants.STATUS_NOTRUN);
		}
		String url = "/" + SysConstants.MGM_VERSION + "/hosts";
		subTask_input.setUrl(url);
		subTask_input.setMethodType(HttpClientUtils.METHOD_POST);
		String param = buildInputHostParam(host);
		subTask_input.setParam(param);
		subTask_input.setPriority(priority);
		return subTasks;
	}

	/**
	 * 构建主机入库所需参数
	 * 
	 * @param host
	 *            主机对象
	 * @return String 主机入库所需参数
	 */
	private String buildInputHostParam(HostEntity host) {
		JSONObject jsonParam = new JSONObject();
		jsonParam.put("cluster_id", host.getCluster().getRelateId());
		jsonParam.put("addr", host.getSshIp());
		jsonParam.put("username", host.getSshUser());
		jsonParam.put("password", host.getSshPassword());
		if (StringUtils.isNotBlank(host.getHddDev())) {
			jsonParam.put("hdd", host.getHddDev().split(","));
		}
		if (StringUtils.isNotBlank(host.getSsdDev())) {
			jsonParam.put("ssd", host.getSsdDev().split(","));
		}
		jsonParam.put("max_container", host.getMaxContainer());
		jsonParam.put("room", host.getRoom());
		jsonParam.put("seat", host.getSeat());
		AreaEntity areaDetail = areaDao.get(host.getCluster().getArea().getId());
		jsonParam.put("nfs_ip", areaDetail.getBackupStorage().getIp());
		jsonParam.put("nfs_dir", areaDetail.getBackupStorage().getDir());
		jsonParam.put("nfs_mount_dir", areaDetail.getBackupStorage().getMountDir());
		jsonParam.put("nfs_mount_opts", areaDetail.getBackupStorage().getMountOpts());
		return jsonParam.toJSONString();
	}

	/**
	 * 构建主机出库任务
	 * 
	 * @param host
	 *            主机对象
	 * @param operateLog
	 *            操作日志对象
	 * @param paramMap
	 *            请求参数
	 * @return 任务对象
	 */
	private TaskEntity buildOutputHostTask(HostEntity host, OperateLogEntity operateLog, Map<String, Object> paramMap) {
		TaskEntity task = new TaskEntity();
		task.setId(PrimaryKeyUtils.uniqueId());
		task.setSite(host.getCluster().getArea().getSite());
		task.setObjType(TaskDictConstants.OBJ_TYPE_HOST);
		task.setObjId(host.getId());
		task.setObjName(host.getName());
		task.setObj(host);
		task.setActionType(TaskDictConstants.ACTION_TYPE_OUTPUT);
		task.setOperateLog(operateLog);
		UserEntity user = getUser();
		String username = user.getUsername();
		task.setOwner(username);
		task.setCreateUserLoginName(username);
		task.setStatus(TaskDictConstants.STATUS_OUTPUT_RUNNING);
		task.setStartDateTime(operateLog.getCreateDateTime());

		List<SubTaskEntity> subTasks = buildOutputHostSubTasks(host, task.getStartDateTime(), paramMap);
		task.setSubTasks(subTasks);

		return task;
	}

	/**
	 * 构建主机出库子任务
	 * 
	 * @param host
	 *            主机对象
	 * @param date
	 *            任务开始时间
	 * @param paramMap
	 *            请求参数
	 * @return 子任务集合
	 */
	private List<SubTaskEntity> buildOutputHostSubTasks(HostEntity host, Date date, Map<String, Object> paramMap) {
		List<SubTaskEntity> subTasks = new ArrayList<SubTaskEntity>(1);
		SubTaskEntity subTask = new SubTaskEntity();
		subTasks.add(subTask);

		subTask.setId(PrimaryKeyUtils.uniqueId());
		subTask.setObjType(SubTaskDictConstants.OBJ_TYPE_HOST);
		subTask.setObjId(host.getId());
		subTask.setObjName(host.getName());
		subTask.setObj(host);
		subTask.setActionType(SubTaskDictConstants.ACTION_TYPE_OUTPUT);
		subTask.setAsync(false);
		subTask.setTimeout(HttpClientUtils.requestConfig.getSocketTimeout() + 10000);
		subTask.setStatus(SubTaskDictConstants.STATUS_RUNNING);
		subTask.setStartDateTime(date);
		String url = null;
		String relateId = host.getRelateId();
		if (relateId != null) {
			String sshUser = (String) paramMap.get("sshUser");
			String sshPassword = (String) paramMap.get("sshPassword");
			url = "/" + SysConstants.MGM_VERSION + "/hosts/" + relateId + "?username=" + sshUser + "&password="
					+ sshPassword;
		}
		subTask.setUrl(url);
		subTask.setMethodType(HttpClientUtils.METHOD_DELETE);
		subTask.setParam(null);
		subTask.setPriority(1);
		return subTasks;
	}

	/**
	 * 构建主机启用任务
	 * 
	 * @param host
	 *            主机对象
	 * @param operateLog
	 *            操作日志对象
	 * @return 任务对象
	 */
	private TaskEntity buildEnableHostTask(HostEntity host, OperateLogEntity operateLog) {
		TaskEntity task = new TaskEntity();
		task.setId(PrimaryKeyUtils.uniqueId());
		task.setSite(host.getCluster().getArea().getSite());
		task.setObjType(TaskDictConstants.OBJ_TYPE_HOST);
		task.setObjId(host.getId());
		task.setObjName(host.getName());
		task.setObj(host);
		task.setActionType(TaskDictConstants.ACTION_TYPE_ENABLE);
		task.setOperateLog(operateLog);
		UserEntity user = getUser();
		String username = user.getUsername();
		task.setOwner(username);
		task.setCreateUserLoginName(username);
		task.setStatus(TaskDictConstants.STATUS_ENABLE_RUNNING);
		task.setStartDateTime(operateLog.getCreateDateTime());

		List<SubTaskEntity> subTasks = buildEnableHostSubTasks(host, task.getStartDateTime());
		task.setSubTasks(subTasks);

		return task;
	}

	/**
	 * 构建主机启用子任务
	 * 
	 * @param host
	 *            主机对象
	 * @param date
	 *            任务开始时间
	 * @return 子任务集合
	 */
	private List<SubTaskEntity> buildEnableHostSubTasks(HostEntity host, Date date) {
		List<SubTaskEntity> subTasks = new ArrayList<SubTaskEntity>(1);
		SubTaskEntity subTask = new SubTaskEntity();
		subTasks.add(subTask);

		subTask.setId(PrimaryKeyUtils.uniqueId());
		subTask.setObjType(SubTaskDictConstants.OBJ_TYPE_HOST);
		subTask.setObjId(host.getId());
		subTask.setObjName(host.getName());
		subTask.setObj(host);
		subTask.setActionType(SubTaskDictConstants.ACTION_TYPE_ENABLE);
		subTask.setAsync(false);
		subTask.setTimeout(HttpClientUtils.requestConfig.getSocketTimeout() + 10000);
		subTask.setStatus(SubTaskDictConstants.STATUS_RUNNING);
		subTask.setStartDateTime(date);
		String url = null;
		String relateId = host.getRelateId();
		if (relateId != null) {
			url = "/" + SysConstants.MGM_VERSION + "/hosts/" + relateId + "/enable";
		}
		subTask.setUrl(url);
		subTask.setMethodType(HttpClientUtils.METHOD_PUT);
		subTask.setParam(null);
		subTask.setPriority(1);
		return subTasks;
	}

	/**
	 * 构建主机停用任务
	 * 
	 * @param host
	 *            主机对象
	 * @param operateLog
	 *            操作日志对象
	 * @return 任务对象
	 */
	private TaskEntity buildDisableHostTask(HostEntity host, OperateLogEntity operateLog) {
		TaskEntity task = new TaskEntity();
		task.setId(PrimaryKeyUtils.uniqueId());
		task.setSite(host.getCluster().getArea().getSite());
		task.setObjType(TaskDictConstants.OBJ_TYPE_HOST);
		task.setObjId(host.getId());
		task.setObjName(host.getName());
		task.setObj(host);
		task.setActionType(TaskDictConstants.ACTION_TYPE_DISABLE);
		task.setOperateLog(operateLog);
		UserEntity user = getUser();
		String username = user.getUsername();
		task.setOwner(username);
		task.setCreateUserLoginName(username);
		task.setStatus(TaskDictConstants.STATUS_DISABLE_RUNNING);
		task.setStartDateTime(operateLog.getCreateDateTime());

		List<SubTaskEntity> subTasks = buildDisableHostSubTasks(host, task.getStartDateTime());
		task.setSubTasks(subTasks);

		return task;
	}

	/**
	 * 构建主机停用子任务
	 * 
	 * @param host
	 *            主机对象
	 * @param date
	 *            任务开始时间
	 * @return 子任务集合
	 */
	private List<SubTaskEntity> buildDisableHostSubTasks(HostEntity host, Date date) {
		List<SubTaskEntity> subTasks = new ArrayList<SubTaskEntity>(1);
		SubTaskEntity subTask = new SubTaskEntity();
		subTasks.add(subTask);

		subTask.setId(PrimaryKeyUtils.uniqueId());
		subTask.setObjType(SubTaskDictConstants.OBJ_TYPE_HOST);
		subTask.setObjId(host.getId());
		subTask.setObjName(host.getName());
		subTask.setObj(host);
		subTask.setActionType(SubTaskDictConstants.ACTION_TYPE_DISABLE);
		subTask.setAsync(false);
		subTask.setTimeout(HttpClientUtils.requestConfig.getSocketTimeout() + 10000);
		subTask.setStatus(SubTaskDictConstants.STATUS_RUNNING);
		subTask.setStartDateTime(date);
		String url = null;
		String relateId = host.getRelateId();
		if (relateId != null) {
			url = "/" + SysConstants.MGM_VERSION + "/hosts/" + relateId + "/disable";
		}
		subTask.setUrl(url);
		subTask.setMethodType(HttpClientUtils.METHOD_PUT);
		subTask.setParam(null);
		subTask.setPriority(1);
		return subTasks;
	}

	/**
	 * 更新MGM上指定的主机信息
	 * 
	 * @param siteId
	 *            站点编码
	 * @param mgmHostId
	 *            MGM主机编码
	 * @param paramMap
	 *            请求参数
	 * @throws APIException
	 *             API异常处理类
	 */
	private void updateHostFromMGM(String siteId, String mgmHostId, Map<String, Object> paramMap) throws APIException {
		JSONObject paramJson = new JSONObject();
		if (paramMap.containsKey("maxContainer")) {
			paramJson.put("max_container", (Integer) paramMap.get("maxContainer"));
		}
		if (!paramJson.isEmpty()) {
			String urlPattern = "/{0}/hosts/{1}";
			String url = MessageFormat.format(urlPattern, SysConstants.MGM_VERSION, mgmHostId);
			RespJson httpRespJson = sendHttpPut(siteId, SysConstants.INTERFACE_TYPE_MGM, url, paramJson.toJSONString());
			if (httpRespJson.getStatus() != HttpStatus.SC_OK) {
				throw new APIException(httpRespJson.getMsg());
			}
		}
	}

}
